﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TunnelsOfDeath.Objects;
using MonoGame;
using Microsoft.Xna.Framework;

namespace TunnelsOfDeath.Managers
{
    class ObjectManager
    {
        /// <summary>
        /// Removes object from map.
        /// </summary>
        /// <param name="_object">Object to remove.</param>
        public void UnregisterObject(Sprite _object)
        {
            if (_object != null)
            {
                Globals.Animated.Remove(_object);
                Globals.Map[(int)_object.position.X, (int)_object.position.Y] = null;
                Globals.PositionUpdate.Remove(_object);

                if (_object.Type == ObjectType.player)
                {
                    Globals.MyCameraManager.UnregisterPlayer((Player)_object);

                    if (((Player)_object).State != PlayerState.FINISHED)
                    {
                        ((Player)_object).State = PlayerState.NOTONMAP;
                    }
                }
            }
        }
        /// <summary>
        /// Adds object to the map and register it as active, if needed.
        /// </summary>
        /// <param name="_object">Object that should be added. Object position should be already set.</param>
        public void RegisterObject(Sprite _object)
        {
            if (_object != null)
            {
                switch (_object.Type)
                {
                    case ObjectType.player:
                        RegisterActiveObject(_object);
                        break;
                    case ObjectType.rock:
                        RegisterStaticObject(_object);
                        break;
                    case ObjectType.dirt:
                        RegisterStaticObject(_object);
                        break;
                    case ObjectType.wall:
                        RegisterStaticObject(_object);
                        break;
                    case ObjectType.enemy:
                        RegisterActiveObject(_object);
                        break;
                    case ObjectType.door:
                        RegisterStaticObject(_object);
                        break;
                    case ObjectType.crystal:
                        RegisterStaticObject(_object);
                        break;
                    case ObjectType.explosion:
                        RegisterActiveObject(_object);
                        break;
                    default:
                        throw new Exception("Unknown sprite type cannot be registered.");
                }
            }


        }


        protected void RegisterStaticObject(Sprite _object)
        {
            Globals.Map[(int)_object.position.X, (int)_object.position.Y] = _object;
        }


        protected void RegisterActiveObject(Sprite _object)
        {
            if (Globals.Animated.IndexOf(_object) == -1)
                Globals.Animated.Add(_object);
            if (Globals.PositionUpdate.IndexOf(_object) == -1)
                Globals.PositionUpdate.Add(_object);

            if (_object is Player)
            {
                if (Globals.ActivePlayersOnMap.IndexOf((Player)_object) == -1)
                    Globals.ActivePlayersOnMap.Add((Player)_object);
            }

            RegisterStaticObject(_object);
        }

        public void GenerateExplosion(Vector2 _position, double _tag)
        {
            foreach (Vector2 position in GetAllFieldsAround())
            {
                Vector2 newPosition = _position+position;
                if (newPosition.X >= 0 || newPosition.X < Globals.Map.GetLength(0))
                {
                    if ((Globals.Map[(int)newPosition.X, (int)newPosition.Y] != null && (Globals.Map[(int)newPosition.X, (int)newPosition.Y].Type != ObjectType.wall && Globals.Map[(int)newPosition.X, (int)newPosition.Y].Type != ObjectType.door)) || Globals.Map[(int)newPosition.X, (int)newPosition.Y] == null)
                    {
                        Explosion explosion = Globals.MainGenerator.GetExplosion(newPosition);
                        explosion.CheckTag(_tag);
                        UnregisterObject(Globals.Map[(int)newPosition.X, (int)newPosition.Y]);
                        RegisterObject(explosion);
                    }
                }

            }
        }

        protected IEnumerable<Vector2> GetAllFieldsAround()
        {
            yield return new Vector2(-1, -1);
            yield return new Vector2(0, -1);
            yield return new Vector2(1, -1);
            yield return new Vector2(-1, 0);
            yield return new Vector2(1, 0);
            yield return new Vector2(-1, 1);
            yield return new Vector2(0, 1);
            yield return new Vector2(1, 1);
            yield return new Vector2(0, 0);
        }

    }

}
